package com.favccxx.search.api;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.favccxx.search.application.ConceptModelService;
import com.favccxx.search.application.DataMapperService;
import com.favccxx.search.application.ProjectService;
import com.favccxx.search.domain.conceptmodel.ConceptModel;
import com.favccxx.search.domain.datamapper.*;
import com.favccxx.search.domain.datamapper.horizontal.HorizontalMapper;
import com.favccxx.search.domain.datamapper.vertical.VerticalMapper;
import com.favccxx.search.domain.project.Project;
import com.favccxx.search.infrastructure.constant.MapperConstants;
import com.favccxx.search.infrastructure.exception.ExceptionCode;
import com.favccxx.search.infrastructure.util.jackson.JacksonUtil;
import com.favccxx.search.infrastructure.util.rest.RestResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author favccxx
 */
@Slf4j
@Api(tags = "5.0 Concept model mapper interface")
@RestController
@RequestMapping("/mapper")
public class DataMapperController {

    @Autowired
    ProjectService projectService;
    @Autowired
    ConceptModelService conceptModelService;
    @Autowired
    DataMapperService mapperService;

    @ApiOperation("find all concept model mappers")
    @GetMapping("/findAll")
    public RestResult<List<DataMapper>> findAll() {
        List<DataMapper> list = mapperService.findAll();
        return RestResult.sucess(list);
    }

    @ApiOperation("save horizontal table mapper")
    @PostMapping("/horizontal/save")
    public RestResult saveHorizontalMapper(
            @RequestParam(value = "projectId", required = true) String projectId,
            @RequestParam(value = "conceptModelCode", required = true) String conceptModelCode,
            @RequestParam(value = "dataSetMappers", required = true) String dataSetMappers,
            @RequestParam(value = "mapperCondition", required = false, defaultValue = "") String mapperCondition) {
        Project project = projectService.findById(projectId);
        if (project == null) {
            return RestResult.error(ExceptionCode.Mapper.MAPPER_SAVE_FAILED, "Horizontal table mapper save failed, invalid projectId: ->" + projectId);
        }

        ConceptModel conceptModel = conceptModelService.findByProjectIdAndCode(projectId, conceptModelCode);
        if (conceptModel == null) {
            return RestResult.error(ExceptionCode.Mapper.MAPPER_SAVE_FAILED, "Horizontal table mapper save failed, invalid conceptModelCode: ->" + conceptModelCode);
        }

        try {
            DataMapper horizontalMapper = new DataMapper();
            horizontalMapper.setProjectId(projectId);
            horizontalMapper.setConceptModelId(conceptModel.getId());
            horizontalMapper.setConceptModelCode(conceptModelCode);
            horizontalMapper.setMapperType(MapperConstants.HORIZONTAL_MAPPER_TYPE);
            horizontalMapper.setMapperCondition(mapperCondition);
            List<DataSetMapper> mapperList = JacksonUtil.fromJson(dataSetMappers, ArrayList.class);
            horizontalMapper.setMapperFields(mapperList);

            mapperService.saveHorizontalMapper(horizontalMapper);

        } catch (Exception e) {
            log.error("saveHorizontalMapper failed", e);
            return RestResult.error(ExceptionCode.Mapper.MAPPER_SAVE_FAILED, "Unknown error.");
        }

        return RestResult.sucess();

    }


    @ApiOperation("save vertical table mapper")
    @PostMapping("/vertical/save")
    public RestResult<DataMapper> saveVerticalMapper(
            @RequestParam(value = "projectId", required = true) String projectId,
            @RequestParam(value = "conceptModelCode", required = true) String conceptModelCode,
            @RequestParam(value = "dataSetMappers", required = true) String dataSetMappers,
            @RequestParam(value = "mapperCondition", required = false, defaultValue = "") String mapperCondition) throws JsonProcessingException {
        Project project = projectService.findById(projectId);
        if (project == null) {
            return RestResult.error(ExceptionCode.Mapper.MAPPER_SAVE_FAILED, "Horizontal table mapper save failed, invalid projectId: ->" + projectId);
        }

        ConceptModel conceptModel = conceptModelService.findByProjectIdAndCode(projectId, conceptModelCode);
        if (conceptModel == null) {
            return RestResult.error(ExceptionCode.Mapper.MAPPER_SAVE_FAILED, "Horizontal table mapper save failed, invalid conceptModelCode: ->" + conceptModelCode);
        }

        try {
            DataMapper verticalMapper = new DataMapper();
            verticalMapper.setProjectId(projectId);
            verticalMapper.setConceptModelCode(conceptModelCode);
            verticalMapper.setMapperType(MapperConstants.VERTICAL_MAPPER_TYPE);

            List<VerticalDataSetMapper> mapperList = JacksonUtil.fromJson(dataSetMappers, ArrayList.class);
            verticalMapper.setMapperFields(mapperList);

            mapperService.saveVerticalMapper(verticalMapper);
        } catch (Exception e) {
            log.error("saveVerticalMapper failed", e);
            return RestResult.error(ExceptionCode.Mapper.MAPPER_SAVE_FAILED, "Unknown error.");
        }
        return RestResult.sucess();
    }


}
